use regex::Regex;
use serde::{ Deserialize, Serialize };
use serde_json::Value;
use crate::REQWEST_CLIENT;
use anyhow::Result;
/// Mapping to [RPT_F10_BASIC_ORGINFO.json](file:///Users/CC/gitee/conanchen/fuquants-workspace/crates/fudacli/eastmoney/sample/RPT_F10_BASIC_ORGINFO.json)
#[derive(Debug, Serialize, Deserialize)]
pub struct RptF10BasicOrgInfo {
    pub version: Option<Value>,
    pub result: RptF10BasicOrgInfoResult,
    pub success: Option<Value>,
    pub message: Option<Value>,
    pub code: Option<Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RptF10BasicOrgInfoResult {
    pub pages: Option<Value>,
    pub data: Vec<RptF10BasicOrgInfoResultData>,
    pub count: Option<Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RptF10BasicOrgInfoResultData {
    #[serde(rename = "SECUCODE")]
    pub secucode: Option<Value>, // 证券代码
    #[serde(rename = "SECURITY_CODE")]
    pub security_code: Option<Value>, // 证券代码（另一种格式或用途）
    #[serde(rename = "SECURITY_NAME_ABBR")]
    pub security_name_abbr: Option<Value>, // 证券简称
    #[serde(rename = "ORG_CODE")]
    pub org_code: Option<Value>, // 组织机构代码
    #[serde(rename = "ORG_NAME")]
    pub org_name: Option<Value>, // 组织机构名称
    #[serde(rename = "ORG_NAME_EN")]
    pub org_name_en: Option<Value>, // 组织机构英文名称
    #[serde(rename = "FORMERNAME")]
    pub former_name: Option<Value>, // 曾用名
    #[serde(rename = "STR_CODEA")]
    pub str_codea: Option<Value>, // 未知字段A的代码
    #[serde(rename = "STR_NAMEA")]
    pub str_namea: Option<Value>, // 未知字段A的名称
    #[serde(rename = "STR_CODEB")]
    pub str_codeb: Option<Value>, // 未知字段B的代码
    #[serde(rename = "STR_NAMEB")]
    pub str_nameb: Option<Value>, // 未知字段B的名称
    #[serde(rename = "STR_CODEH")]
    pub str_codeh: Option<Value>, // 未知字段H的代码
    #[serde(rename = "STR_NAMEH")]
    pub str_nameh: Option<Value>, // 未知字段H的名称
    #[serde(rename = "SECURITY_TYPE")]
    pub security_type: Option<Value>, // 证券类型
    #[serde(rename = "EM2016")]
    pub em2016: Option<Value>, // 2016年EM（可能是某种指标或评级）
    #[serde(rename = "TRADE_MARKET")]
    pub trade_market: Option<Value>, // 交易市场
    #[serde(rename = "INDUSTRYCSRC1")]
    pub industry_csrc1: Option<Value>, // 行业分类代码（CSRC1）
    #[serde(rename = "PRESIDENT")]
    pub president: Option<Value>, // 总裁或负责人
    #[serde(rename = "LEGAL_PERSON")]
    pub legal_person: Option<Value>, // 法定代表人
    #[serde(rename = "SECRETARY")]
    pub secretary: Option<Value>, // 秘书或秘书长
    #[serde(rename = "CHAIRMAN")]
    pub chairman: Option<Value>, // 主席或董事长
    #[serde(rename = "SECPRESENT")]
    pub secpresent: Option<Value>, // 证券代表
    #[serde(rename = "INDEDIRECTORS")]
    pub indirectors: Option<Value>, // 独立董事
    #[serde(rename = "ORG_TEL")]
    pub org_tel: Option<Value>, // 组织机构电话
    #[serde(rename = "ORG_EMAIL")]
    pub org_email: Option<Value>, // 组织机构邮箱
    #[serde(rename = "ORG_FAX")]
    pub org_fax: Option<Value>, // 组织机构传真
    #[serde(rename = "ORG_WEB")]
    pub org_web: Option<Value>, // 组织机构网站
    #[serde(rename = "ADDRESS")]
    pub address: Option<Value>, // 地址
    #[serde(rename = "REG_ADDRESS")]
    pub reg_address: Option<Value>, // 注册地址
    #[serde(rename = "PROVINCE")]
    pub province: Option<Value>, // 省份
    #[serde(rename = "ADDRESS_POSTCODE")]
    pub address_postcode: Option<Value>, // 地址邮编
    #[serde(rename = "REG_CAPITAL")]
    pub reg_capital: Option<Value>, // 注册资金
    #[serde(rename = "REG_NUM")]
    pub reg_num: Option<Value>, // 注册号
    #[serde(rename = "EMP_NUM")]
    pub emp_num: Option<Value>, // 员工数量
    #[serde(rename = "TATOLNUMBER")]
    pub tatolnumber: Option<Value>, // 总数量（可能是某种特定类型的数量）
    #[serde(rename = "LAW_FIRM")]
    pub law_firm: Option<Value>, // 律师事务所
    #[serde(rename = "ACCOUNTFIRM_NAME")]
    pub accountfirm_name: Option<Value>, // 会计师事务所名称
    #[serde(rename = "ORG_PROFILE")]
    pub org_profile: Option<Value>, // 组织机构简介
    #[serde(rename = "BUSINESS_SCOPE")]
    pub business_scope: Option<Value>, // 经营范围
    #[serde(rename = "TRADE_MARKETT")]
    pub trade_markett: Option<Value>, // 交易市场（可能是字段名有误，通常应该是TRADE_MARKET）
    #[serde(rename = "TRADE_MARKET_CODE")]
    pub trade_market_code: Option<Value>, // 交易市场代码
    #[serde(rename = "SECURITY_TYPEE")]
    pub security_typee: Option<Value>, // 证券类型（可能是字段名有误，通常应该是SECURITY_TYPE）
    #[serde(rename = "SECURITY_TYPE_CODE")]
    pub security_type_code: Option<Value>, // 证券类型代码
    #[serde(rename = "EXPAND_NAME_ABBR")]
    pub expand_name_abbr: Option<Value>, // 扩展名称缩写
    #[serde(rename = "EXPAND_NAME_PINYIN")]
    pub expand_name_pinyin: Option<Value>, // 扩展名称拼音，
}

impl RptF10BasicOrgInfo {
    /// code: 000001.SZ or 600519.SH
    ///
    // Referer: https://emweb.securities.eastmoney.com/pc_hsf10/pages/index.html?type=web&code=SZ000001&color=b#/gsgk
    //
    // Data: https://datacenter.eastmoney.com/securities/api/data/v1/get?reportName=RPT_F10_BASIC_ORGINFO&columns=SECUCODE%2CSECURITY_CODE%2CSECURITY_NAME_ABBR%2CORG_CODE%2CORG_NAME%2CORG_NAME_EN%2CFORMERNAME%2CSTR_CODEA%2CSTR_NAMEA%2CSTR_CODEB%2CSTR_NAMEB%2CSTR_CODEH%2CSTR_NAMEH%2CSECURITY_TYPE%2CEM2016%2CTRADE_MARKET%2CINDUSTRYCSRC1%2CPRESIDENT%2CLEGAL_PERSON%2CSECRETARY%2CCHAIRMAN%2CSECPRESENT%2CINDEDIRECTORS%2CORG_TEL%2CORG_EMAIL%2CORG_FAX%2CORG_WEB%2CADDRESS%2CREG_ADDRESS%2CPROVINCE%2CADDRESS_POSTCODE%2CREG_CAPITAL%2CREG_NUM%2CEMP_NUM%2CTATOLNUMBER%2CLAW_FIRM%2CACCOUNTFIRM_NAME%2CORG_PROFILE%2CBUSINESS_SCOPE%2CTRADE_MARKETT%2CTRADE_MARKET_CODE%2CSECURITY_TYPEE%2CSECURITY_TYPE_CODE%2CEXPAND_NAME_ABBR%2CEXPAND_NAME_PINYIN&quoteColumns=&filter=(SECUCODE%3D%22000001.SZ%22)&pageNumber=1&pageSize=1&sortTypes=&sortColumns=&source=HSF10&client=PC&v=016640318038269908
    pub async fn rpt_f10_basic_orginfo(code: &str) -> Result<RptF10BasicOrgInfo> {
        let re = Regex::new(r"^\d{6}\.(?:SZ|SH)$").unwrap();
        assert!(
            re.is_match(code),
            "Code must be in the format 'NNNNNN.SZ' or 'NNNNNN.SH', where N is a digit."
        );

        // GET /securities/api/data/v1/get?reportName=RPT_F10_BASIC_ORGINFO&columns=SECUCODE%2CSECURITY_CODE%2CSECURITY_NAME_ABBR%2CORG_CODE%2CORG_NAME%2CORG_NAME_EN%2CFORMERNAME%2CSTR_CODEA%2CSTR_NAMEA%2CSTR_CODEB%2CSTR_NAMEB%2CSTR_CODEH%2CSTR_NAMEH%2CSECURITY_TYPE%2CEM2016%2CTRADE_MARKET%2CINDUSTRYCSRC1%2CPRESIDENT%2CLEGAL_PERSON%2CSECRETARY%2CCHAIRMAN%2CSECPRESENT%2CINDEDIRECTORS%2CORG_TEL%2CORG_EMAIL%2CORG_FAX%2CORG_WEB%2CADDRESS%2CREG_ADDRESS%2CPROVINCE%2CADDRESS_POSTCODE%2CREG_CAPITAL%2CREG_NUM%2CEMP_NUM%2CTATOLNUMBER%2CLAW_FIRM%2CACCOUNTFIRM_NAME%2CORG_PROFILE%2CBUSINESS_SCOPE%2CTRADE_MARKETT%2CTRADE_MARKET_CODE%2CSECURITY_TYPEE%2CSECURITY_TYPE_CODE%2CEXPAND_NAME_ABBR%2CEXPAND_NAME_PINYIN&quoteColumns=&filter=(SECUCODE%3D%22000001.SZ%22)&pageNumber=1&pageSize=1&sortTypes=&sortColumns=&source=HSF10&client=PC&v=01267543553231265 HTTP/1.1
        // Accept: */*
        // Accept-Encoding: gzip, deflate, br
        // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
        // Cache-Control: no-cache
        // Connection: keep-alive
        // Host: datacenter.eastmoney.com
        // Origin: https://emweb.securities.eastmoney.com
        // Pragma: no-cache
        // Referer: https://emweb.securities.eastmoney.com/
        // Sec-Fetch-Dest: empty
        // Sec-Fetch-Mode: cors
        // Sec-Fetch-Site: same-site
        // User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
        // sec-ch-ua: "Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"
        // sec-ch-ua-mobile: ?0
        // sec-ch-ua-platform: "macOS"

        let host = "datacenter.eastmoney.com";
        // Query String Parameters:
        //
        let report_name = "RPT_F10_BASIC_ORGINFO";
        let columns =
            "SECUCODE,SECURITY_CODE,SECURITY_NAME_ABBR,ORG_CODE,ORG_NAME,ORG_NAME_EN,FORMERNAME,STR_CODEA,STR_NAMEA,STR_CODEB,STR_NAMEB,STR_CODEH,STR_NAMEH,SECURITY_TYPE,EM2016,TRADE_MARKET,INDUSTRYCSRC1,PRESIDENT,LEGAL_PERSON,SECRETARY,CHAIRMAN,SECPRESENT,INDEDIRECTORS,ORG_TEL,ORG_EMAIL,ORG_FAX,ORG_WEB,ADDRESS,REG_ADDRESS,PROVINCE,ADDRESS_POSTCODE,REG_CAPITAL,REG_NUM,EMP_NUM,TATOLNUMBER,LAW_FIRM,ACCOUNTFIRM_NAME,ORG_PROFILE,BUSINESS_SCOPE,TRADE_MARKETT,TRADE_MARKET_CODE,SECURITY_TYPEE,SECURITY_TYPE_CODE,EXPAND_NAME_ABBR,EXPAND_NAME_PINYIN";
        let quote_columns = "";
        let filter = format!("(SECUCODE=\"{code}\")");
        let page_number = 1;
        let page_size = 1;
        // sortTypes:
        // sortColumns:
        let source = "HSF10";
        let client_p = "PC";
        let v = utils::duration_ms_since_epoch(); //013403382009916798

        let request_url = format!(
            "https://{host}/securities/api/data/v1/get?reportName={report_name}&columns={columns}&quoteColumns={quote_columns}&filter={filter}&pageNumber={page_number}&pageSize={page_size}&sortTypes=&sortColumns=&source={source}&client={client_p}&v={v}"
        );

        println!("\n request_url= {request_url}\n");

        let response = REQWEST_CLIENT.get(request_url)
            .header(reqwest::header::ACCEPT, "*/*")
            .header(reqwest::header::ACCEPT_ENCODING, "gzip, deflate, br")
            .header(reqwest::header::ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9,en;q=0.8")
            .header(reqwest::header::CACHE_CONTROL, "no-cache")
            .header(reqwest::header::CONNECTION, "keep-alive")
            // .header(reqwest::header::COOKIE, "qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-16%2016%3A57%3A06@%23%24%u4E2D%u822A%u65B0%u8D77%u822A%u7075%u6D3B%u914D%u7F6E%u6DF7%u5408A@%23%24005537; EMFUND1=01-16%2017%3A04%3A53@%23%24%u91D1%u4FE1%u6D88%u8D39%u5347%u7EA7%u80A1%u7968A@%23%24006692; EMFUND2=01-16%2020%3A01%3A56@%23%24%u5357%u65B9%u4E0A%u8BC1380ETF@%23%24510290; EMFUND3=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND4=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND5=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND6=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND7=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND8=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND9=02-02 10:30:22@#$%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; st_asi=delete; HAList=ty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6%2Cty-1-603135-%u4E2D%u91CD%u79D1%u6280%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-002400-%u7701%u5E7F%u96C6%u56E2%2Cty-1-601127-%u8D5B%u529B%u65AF; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=438; st_psi=20240226102321941-113200301321-9024721593")
            .header(reqwest::header::HOST, format!("{host}"))
            .header(reqwest::header::ORIGIN, "https://emweb.securities.eastmoney.com")
            .header(reqwest::header::PRAGMA, "no-cache")
            .header(reqwest::header::REFERER, "https://emweb.securities.eastmoney.com/")
            .header(
                reqwest::header::USER_AGENT,
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
            )
            .header(
                "Sec-Ch-Ua",
                "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\""
            )
            .header("Sec-Ch-Ua-Mobile", "?0")
            .header("Sec-Ch-Ua-Platform", "\"macOS\"")
            .header("Sec-Fetch-Dest", "empty")
            .header("Sec-Fetch-Mode", "cors")
            .header("Sec-Fetch-Site", "same-origin")
            .send().await?;

        let body = response.text().await?;

        // println!("*** body={}\n\nhangqin\n\n", body);

        let fund: RptF10BasicOrgInfo = serde_json::from_str(&body)?;

        // println!("{:?}", fund);

        Ok(fund)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[tokio::test]
    async fn test_stock_rpt_f10_basic_orginfo() {
        let result = RptF10BasicOrgInfo::rpt_f10_basic_orginfo("300529.SZ").await;

        assert_eq!(result.is_ok(), true);
        if let Ok(basic_org_info) = result {
            assert_eq!(basic_org_info.message, Some(Value::String("ok".to_string())));
            assert_eq!(
                basic_org_info.result.data[0].security_code,
                Some(Value::String("300529".to_string()))
            );
            println!("basic_org_info = {:?}\n", basic_org_info);
        }
    }
}
